import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import math

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def direct_line_symmetry(points, A, B, C):
    """
    使用直接公式计算点关于直线的对称点
    公式: (x', y') = (x - 2A*(Ax+By+C)/(A²+B²), y - 2B*(Ax+By+C)/(A²+B²))
    """
    points = np.array(points)
    denominator = A**2 + B**2
   
    if denominator < 1e-10:
        raise ValueError("直线方程系数A和B不能同时为零")
   
    symmetric_points = []
    for point in points:
        x, y = point
        factor = 2 * (A*x + B*y + C) / denominator
        x_sym = x - A * factor
        y_sym = y - B * factor
        symmetric_points.append([x_sym, y_sym])
   
    return np.array(symmetric_points)

def visualize_symmetry(points, A, B, C, title="二维图形关于直线的对称变换"):
    """
    可视化原始图形和对称后的图形
    """
    # 计算对称点
    symmetric_points = direct_line_symmetry(points, A, B, C)
    
    # 创建图形和坐标轴
    fig, ax = plt.subplots(1, 1, figsize=(12, 10))
    
    # 确保图形闭合
    original_closed = np.vstack([points, points[0]])
    symmetric_closed = np.vstack([symmetric_points, symmetric_points[0]])
    
    # 绘制原始图形（蓝色）
    original_polygon = Polygon(points, closed=True, alpha=0.6, 
                              facecolor='lightblue', edgecolor='blue', linewidth=2, label='原始图形')
    ax.add_patch(original_polygon)
    
    # 绘制对称图形（红色）
    symmetric_polygon = Polygon(symmetric_points, closed=True, alpha=0.6, 
                               facecolor='lightcoral', edgecolor='red', linewidth=2, label='对称图形')
    ax.add_patch(symmetric_polygon)
    
    # 绘制对称轴直线
    x_min, x_max = ax.get_xlim()
    y_min, y_max = ax.get_ylim()
    
    # 生成直线上的点
    if B != 0:
        x_line = np.array([x_min - 2, x_max + 2])  # 扩展范围确保直线可见
        y_line = (-A * x_line - C) / B
    else:  # 垂直直线
        x_line = np.array([-C/A, -C/A])
        y_line = np.array([y_min - 2, y_max + 2])
    
    ax.plot(x_line, y_line, 'g--', linewidth=2, label=f'对称轴: {A}x+{B}y+{C}=0')
    
    # 绘制顶点连线，显示对称关系
    for i, (orig, sym) in enumerate(zip(points, symmetric_points)):
        ax.plot([orig[0], sym[0]], [orig[1], sym[1]], 'gray', linestyle=':', alpha=0.7)
        # 标记顶点编号
        ax.text(orig[0], orig[1], f' P{i}', fontsize=10, ha='left', va='bottom')
        ax.text(sym[0], sym[1], f" P{i}'", fontsize=10, ha='left', va='bottom')
    
    # 设置图形属性
    ax.set_xlabel('X坐标')
    ax.set_ylabel('Y坐标')
    ax.set_title(title, fontsize=14, fontweight='bold')
    ax.grid(True, alpha=0.3)
    ax.legend()
    ax.set_aspect('equal')
    
    # 自动调整坐标轴范围
    all_points = np.vstack([points, symmetric_points])
    margin = 0.5
    ax.set_xlim(all_points[:, 0].min() - margin, all_points[:, 0].max() + margin)
    ax.set_ylim(all_points[:, 1].min() - margin, all_points[:, 1].max() + margin)
    
    plt.tight_layout()
    plt.show()
    
    return symmetric_points

def compare_methods():
    """测试并可视化对称变换"""
    # 测试点集（三角形）
    test_points = np.array([[2, 1], [5, 2], [3, 4]])
    A, B, C = 1, -2, 3  # 直线方程: x - 2y + 3 = 0
    
    print("原始顶点坐标:")
    for i, point in enumerate(test_points):
        print(f"P{i}: ({point[0]}, {point[1]})")
    
    result = direct_line_symmetry(test_points, A, B, C)
    
    print("\n对称后顶点坐标:")
    for i, point in enumerate(result):
        print(f"P{i}': ({point[0]:.2f}, {point[1]:.2f})")
    
    # 可视化
    symmetric_points = visualize_symmetry(test_points, A, B, C, 
                                         f"三角形关于直线 {A}x+{B}y+{C}=0 的对称变换")
    
    return symmetric_points

# 额外的示例：绘制不同图形的对称变换
def additional_examples():
    """更多对称变换示例"""
    
    # 示例1：矩形关于y轴对称
    rectangle_points = np.array([[1, 1], [4, 1], [4, 3], [1, 3]])
    A, B, C = 1, 0, 0  # 直线x=0 (y轴)
    visualize_symmetry(rectangle_points, A, B, C, "矩形关于y轴的对称变换")
    
    # 示例2：五边形关于x=y对称
    pentagon_points = np.array([[2, 1], [3, 2], [2.5, 3], [1.5, 3], [1, 2]])
    A, B, C = 1, -1, 0  # 直线x-y=0
    visualize_symmetry(pentagon_points, A, B, C, "五边形关于直线y=x的对称变换")

# 运行测试
if __name__ == "__main__":
    print("=" * 60)
    print("二维图形对称变换可视化演示")
    print("=" * 60)
    
    # 主要测试
    symmetric_result = compare_methods()
    
    # 询问是否运行更多示例
    print("\n是否运行更多示例？(y/n)")
    user_input = input().strip().lower()
    if user_input == 'y' or user_input == 'yes':
        additional_examples()
    
    print("程序执行完毕！")